/**
 Copyright (C) 2013 Yuyao Liang

 This source code is release under the BSD License.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.

 Created on Dec 9, 2013 10:33:58 AM
 */
package com.googlecode.backtest.rule.criteria;

import java.util.ArrayList;
import java.util.List;

import com.googlecode.backtest.dataset.IBackTestStockDataset;
import com.googlecode.backtest.dataset.manager.DataReadyEvent;
import com.googlecode.backtest.rule.IBackTestParameters;
import com.googlecode.backtest.rule.action.BackTestAction;
import com.googlecode.backtest.rule.action.BackTestActionMethod;
import com.googlecode.backtest.rule.action.IBackTestActions;

/**
 * @author lianyuy
 * 
 */
public class BackTestThresholdCriteria extends BackTestCriteria implements
		IBackTestThresholdCriteria<IBackTestActions, IBackTestParameters> {

	private double buythreshold;
	private double sellthreshold;

	private List<IBackTestStockDataset> dataset = new ArrayList<IBackTestStockDataset>();

	private final String ID = getClass().getName();
	private final String VERSION = Messages
			.getString("BackTestThresholdCriteria.VERSION"); //$NON-NLS-1$
	private final String KEY = Messages
			.getString("BackTestThresholdCriteria.key"); //$NON-NLS-1$
	public static final String SellThreshold = Messages
			.getString("BackTestThresholdCriteria.SELL"); //$NON-NLS-1$
	public static final String BuyThreshold = Messages
			.getString("BackTestThresholdCriteria.BUY"); //$NON-NLS-1$
	public static final String DatasetKey = Messages
			.getString("BackTestThresholdCriteria.DATA_KEY"); //$NON-NLS-1$

	/**
	 * @param dataset
	 * @param id
	 */
	public BackTestThresholdCriteria(String id, List<String> data_ids,
			IBackTestParameters parameter) {
		super(id, data_ids, parameter);
		sellthreshold = Double.parseDouble(parameter
				.getParameter(SellThreshold));
		buythreshold = Double.parseDouble(parameter.getParameter(BuyThreshold));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.googlecode.backtest.rule.IAlgorithm#getKey()
	 */
	@Override
	public String getKey() {
		return KEY;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.google.srclib.base.IDable#getID()
	 */
	@Override
	public String getID() {
		return ID;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.google.srclib.base.Versionable#getVersion()
	 */
	@Override
	public String getVersion() {
		return VERSION;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.googlecode.backtest.rule.criteria.IBackTestThresholdCriteria#
	 * setBuyThreshold(double)
	 */
	@Override
	public void setBuyThreshold(double value) {
		buythreshold = value;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.googlecode.backtest.rule.criteria.IBackTestThresholdCriteria#
	 * getBuyThreshold()
	 */
	@Override
	public double getBuyThreshold() {
		return buythreshold;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.googlecode.backtest.rule.criteria.IBackTestThresholdCriteria#
	 * setExitThreshold(double)
	 */
	@Override
	public void setExitThreshold(double value) {
		sellthreshold = value;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.googlecode.backtest.rule.criteria.IBackTestThresholdCriteria#
	 * getExitThreshold()
	 */
	@Override
	public double getExitThreshold() {
		return sellthreshold;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.googlecode.backtest.rule.criteria.IBackTestCriteria#calculate()
	 */
	@Override
	public boolean calculate() {
		if (dataset.size() == 0) {
			return false;
		}
		String indexkey = parameter.getParameter(DatasetKey);
		IBackTestStockDataset ohlcdata = dataset.get(0);
		dates = ohlcdata.getDates();
		values = ohlcdata.getArray(indexkey);
		if (values == null) {
			return false;
		}

		boolean buy = true;

		for (int index = 0; index < values.length - 1; index++) {
			double value0 = values[index];
			double value1 = values[index + 1];

			if (buy) {
				if (value0 < buythreshold && value1 > buythreshold) {
					actions.add(new BackTestAction(dates[index],
							BackTestActionMethod.Buy, 1.0));
					buy = !buy;
				}
			} else {
				if (value0 > sellthreshold && value1 < sellthreshold) {
					actions.add(new BackTestAction(dates[index],
							BackTestActionMethod.Sell, 1.0));
					buy = !buy;
				}
			}
		}

		manager.putData(this.getGUID(), actions);

		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.googlecode.backtest.dataset.manager.DataReadyEventListener#OnDataReady
	 * (com.googlecode.backtest.dataset.manager.DataReadyEvent)
	 */
	@Override
	public void OnDataReady(DataReadyEvent event) {
		super.OnDataReady(event);
		String key = event.getKey();
		int index = data_ids.indexOf(key);

		dataset.add(index,
				(IBackTestStockDataset) event.getManager().getData(key));

		if (calculate()) {
			System.out.println("Criteria Data ready!"); //$NON-NLS-1$
		}
	}

}
